<?php
/*
Name: PHP File Cache
URI: http://www.5gme.com/boboweb
Description: PHP File Cache module is a simple file cache module.
Author: boboweb
Version: 0.1 alpha
Author URI: http://www.5gme.com/boboweb
*/

class FileCache {
	var $cacheRoot = './.cache/';
	var $fileExt = '.f~';
	var $dirHashLevel = 1;
	var $items;
	var $paths;

	// 构造函数
	function FileCache() {
		if( defined('ABSCACHE') ) {
			$this->cacheRoot = ABSCACHE;
		}
		$this->items = array();
		$this->paths = array();
	}

	// expire
	function expire($key, $expire = 0) {
		$p = $this->getFilePath($key);
		if( file_exists($p) ) {
			$time1 = filemtime($p);
			$time2 = time();

			return ( ($time2 - $time1) > $expire );
		}

		return true;
	}
	
	// get
	function get($key, $value = null) {
		if( array_key_exists($key, $this->items) ) {
			return $this->items[$key];
		} else {
			return $this->read($key, $value);
		}
		return $value;
	}

	// set
	function set($key, $value = null, $expire = 0) {
		if( $expire > 0 ) {
			return $this->rewrite($key, $value, $expire);
		} else {
			return $this->write($key, $value, $expire);
		}
	}

	// del
	function del($key) {
		if( array_key_exists($key, $this->items) ) {
			unset( $this->items[$key] );
		}
		$p = $this->getFilePath($key);
		if( file_exists( $p ) ) {
			@unlink($p);
			return $p;
		}
	}

	////// 私有方法 //////

	// add item
	function addItem($key, $value = null) {
		$this->items[$key] = $value;
		return $value;
	}

	// read
	function read($key, $value = null) {
		$p = $this->getFilePath($key);
		
		if( file_exists( $p ) ) {
			$v = maybeUnserialize( file_get_contents($p) );
			
			$this->addItem($key, $v);
			return $v;
		}

		return $value;
	}

	// write
	function write($key, $value = null) {
		$p = $this->getFilePath($key);

		//$maybe_created = !file_exists($p);
		if( @file_put_contents( $p, maybeSerialize($value) ) ) {
			// chmod($p, 0777);
			//if( $maybe_created ) {
				//chmod($p, 0777);
			//}
			$this->addItem($key, $value);
			return true;
		} else {
			return false;
		}
	}

	// rewrite 
	function rewrite($key, $value = null, $expire = 0) {
		$p = $this->getFilePath($key);

		if( file_exists($p) ) {
			$time1 = filemtime($p);
			$time2 = time();
			if( ($time2 - $time1) > $expire ) {
				return $this->write($key, $value);
			}
		} else {
			return $this->write($key, $value);
		}
	}
	
	// getItemLastUpdate
	function getItemLastUpdate($key, $fmt = 'Y-m-d H:i:s') {
		$p = $this->getFilePath($key);
		if( file_exists($p) ) {
			$time1 = filemtime($p);
			return date($fmt, $time1);
		}
		return NULL;
	}

	// getFilePath
	function getFilePath($key) {
		if( array_key_exists($key, $this->paths) ) {
			return $this->paths[$key];
		}

		$md5_key = md5($key);
		$cache_path = $this->cacheRoot . substr($md5_key, 0, 2); // . '/' . substr($md5_key, 2, 2) . '/';
		if( !file_exists($cache_path) ) {
			mkdir($cache_path, 0777);
			chmod($cache_path, 0777);
		}
		if( $this->dirHashLevel>1 ) {
			$cache_path .= '/' . substr($md5_key, 2, 2);
			if( !file_exists($cache_path) ) {
				mkdir($cache_path, 0777);
				chmod($cache_path, 0777);
			}
		}
		$cache_path .= '/';
		$cache_path1 = $cache_path . $md5_key . $this->fileExt;

		$this->paths[$key] = $cache_path1;
		return  $cache_path1;
	}
	
}


/* ******* Serialize Functions ******* */

// function maybeSerialize
if( !function_exists('maybeSerialize') ) {
	function maybeSerialize($data) {
		if ( is_string($data) )
			$data = trim($data);
		elseif ( is_array($data) || is_object($data) )
			return serialize($data);
		if ( isSerialized($data) )
			return serialize($data);
		return $data;
	}
}
	
// function maybeUnserialize
if( !function_exists('maybeUnserialize') ) {
	function maybeUnserialize($original) {
		if ( isSerialized($original) ) {
			if ( false !== $gm = @unserialize($original) ) return $gm;
		}
		return $original;
	}
}
	
// function isSerialized
if( !function_exists('isSerialized') ) {
	function isSerialized($data) {
		// if it isn't a string, it isn't serialized
		if ( !is_string($data) )
			return false;
	
		$data = trim($data);
		if ( 'N;' == $data )
			return true;
	
		if ( !preg_match('/^([adObis]):/', $data, $badions) )
			return false;
	
		switch ( $badions[1] ) :
			case 'a' :
			case 'O' :
			case 's' :
				if ( preg_match("/^{$badions[1]}:[0-9]+:.*[;}]\$/s", $data) )
					return true;
				break;
			case 'b' :
			case 'i' :
			case 'd' :
				if ( preg_match("/^{$badions[1]}:[0-9.E-]+;\$/", $data) )
					return true;
				break;
		endswitch;
	
		return false;
	}
}
?>